﻿#pragma once

#include "../Enums.h"
#include "Stat.h"
#include <string>
#include <vector>
#include <cmath>
#include <optional>
#include "../../stringhelper.h"

//C# TO C++ CONVERTER NOTE: Forward class declarations:
class RandomItemStat;
class ExpireInfo;
class RentalInformation;
class Awake;

class ItemInfo
{
public:
    int Index = 0;
    std::string Name = std::string::Empty;
    ItemType Type = static_cast<ItemType>(0);
    ItemGrade Grade = static_cast<ItemGrade>(0);
    RequiredType RequiredType = RequiredType::Level;
    RequiredClass RequiredClass = RequiredClass::None;
    RequiredGender RequiredGender = RequiredGender::None;
    ItemSet Set = static_cast<ItemSet>(0);

    short Shape = 0;
    unsigned char Weight = 0, Light = 0, RequiredAmount = 0;

    unsigned short Image = 0, Durability = 0;

    unsigned int Price = 0;
    unsigned short StackSize = 1;

    bool StartItem = false;
    unsigned char Effect = 0;

    bool NeedIdentify = false, ShowGroupPickup = false, GlobalDropNotify = false;
    bool ClassBased = false;
    bool LevelBased = false;
    bool CanMine = false;
    bool CanFastRun = false;
    bool CanAwakening = false;

    BindMode Bind = BindMode::None;

    SpecialItemMode Unique = SpecialItemMode::None;
    unsigned char RandomStatsId = 0;
    RandomItemStat *RandomStats;
    std::string ToolTip = std::string::Empty;

    unsigned char Slots = 0;

    Stats *Stats;

    virtual ~ItemInfo()
    {
        delete RandomStats;
        delete Stats;
    }

    bool isConsumable() const;
    bool isFishingRod() const;

    std::string getFriendlyName() const;

    ItemInfo();

    ItemInfo(BinaryReader *reader, int version = int::MaxValue, int customVersion = int::MaxValue);



    void Save(BinaryWriter *writer);

    static ItemInfo *FromText(const std::string &text);

    std::string ToText();

    std::string ToString();

};

class UserItem
{
public:
    unsigned long long UniqueID = 0;
    int ItemIndex = 0;

    ItemInfo *Info;
    unsigned short CurrentDura = 0, MaxDura = 0;
    unsigned short Count = 1, GemCount = 0;

    RefinedValue RefinedValue = RefinedValue::None;
    unsigned char RefineAdded = 0;
    int RefineSuccessChance = 0;

    bool DuraChanged = false;
    int SoulBoundId = -1;
    bool Identified = false;
    bool Cursed = false;

    int WeddingRing = -1;

    std::vector<UserItem*> Slots = std::vector<UserItem*>(0);

    DateTime BuybackExpiryDate;

    ExpireInfo *ExpireInfo;
    RentalInformation *RentalInformation;

    bool IsShopItem = false;

    Awake *Awake = new Awake();

    Stats *AddedStats;

    virtual ~UserItem()
    {
        delete Info;
        delete ExpireInfo;
        delete RentalInformation;
        delete Awake;
        delete AddedStats;
    }

    bool isAdded() const;

    int getWeight() const;

    std::string getFriendlyName() const;

    UserItem(ItemInfo *info);
    UserItem(BinaryReader *reader, int version = int::MaxValue, int customVersion = int::MaxValue);

    void Save(BinaryWriter *writer);

    int GetTotal(Stat type);

    unsigned int Price();
    unsigned int RepairPrice();

    unsigned int Quality();

    unsigned int AwakeningPrice();

    unsigned int DisassemblePrice();

    unsigned int DowngradePrice();

    unsigned int ResetPrice();
    void SetSlotSize(std::optional<int> &size = std::nullopt);

    unsigned short getImage() const;

    UserItem *Clone();

};

class ExpireInfo
{
public:
    DateTime ExpiryDate;

    ExpireInfo();

    ExpireInfo(BinaryReader *reader, int version = int::MaxValue, int Customversion = int::MaxValue);

    void Save(BinaryWriter *writer);
};

class RentalInformation
{
public:
    std::string OwnerName;
    BindMode BindingFlags = BindMode::None;
    DateTime ExpiryDate;
    bool RentalLocked = false;

    RentalInformation();

    RentalInformation(BinaryReader *reader, int version = int::MaxValue, int CustomVersion = int::MaxValue);

    void Save(BinaryWriter *writer);
};

class GameShopItem
{
public:
    int ItemIndex = 0;
    int GIndex = 0;
    ItemInfo *Info;
    unsigned int GoldPrice = 0;
    unsigned int CreditPrice = 0;
    unsigned short Count = 1;
    std::string Class = "";
    std::string Category = "";
    int Stock = 0;
    bool iStock = false;
    bool Deal = false;
    bool TopItem = false;
    DateTime Date;

    virtual ~GameShopItem()
    {
        delete Info;
    }

    GameShopItem();

    GameShopItem(BinaryReader *reader, int version = int::MaxValue, int Customversion = int::MaxValue);

    GameShopItem(BinaryReader *reader, bool packet = false);

    void Save(BinaryWriter *writer, bool packet = false);

    std::string ToString();

};

class Awake
{
    //Awake Option
public:
    static unsigned char AwakeSuccessRate;
    static unsigned char AwakeHitRate;
    static int MaxAwakeLevel;
    static unsigned char Awake_WeaponRate;
    static unsigned char Awake_HelmetRate;
    static unsigned char Awake_ArmorRate;
    static unsigned char AwakeChanceMin;
    static std::vector<float> AwakeMaterialRate;
    static std::vector<unsigned char> AwakeChanceMax;
    static std::vector<std::vector<std::vector<unsigned char>>> AwakeMaterials;

    AwakeType Type = AwakeType::None;
private:
//C# TO C++ CONVERTER WARNING: C++ has no equivalent to a 'readonly' collection which allows modification of internal state:
//ORIGINAL LINE: readonly List<byte> listAwake = new List<byte>();
    std::vector<unsigned char> listAwake = std::vector<unsigned char>();

public:
    Awake();

    Awake(BinaryReader *reader);

    void Save(BinaryWriter *writer);
    bool IsMaxLevel();

    int GetAwakeLevel();

    unsigned char GetAwakeValue();

    bool CheckAwakening(UserItem *item, AwakeType type);

    int UpgradeAwake(UserItem *item, AwakeType type, std::vector<bool> &isHit);

    int RemoveAwake();

    int GetAwakeLevelValue(int i);

    unsigned char GetDC();
    unsigned char GetMC();
    unsigned char GetSC();
    unsigned char GetAC();
    unsigned char GetMAC();
    unsigned char GetHPMP();

private:
    std::vector<bool> MakeHit(int maxValue, int &makeValue);

    std::vector<bool> Awakening(UserItem *item);
};


class ItemRentalInformation
{
public:
    unsigned long long ItemId = 0;
    std::string ItemName;
    std::string RentingPlayerName;
    DateTime ItemReturnDate;

    ItemRentalInformation();

    ItemRentalInformation(BinaryReader *reader);

    void Save(BinaryWriter *writer);
};


class ItemSets
{
public:
    ItemSet Set = static_cast<ItemSet>(0);
    std::vector<ItemType> Type;
private:
    unsigned char getAmount() const;
public:
    unsigned char Count = 0;
    bool getSetComplete() const;
};


class RandomItemStat
{
public:
    unsigned char MaxDuraChance = 0, MaxDuraStatChance = 0, MaxDuraMaxStat = 0;
    unsigned char MaxAcChance = 0, MaxAcStatChance = 0, MaxAcMaxStat = 0, MaxMacChance = 0, MaxMacStatChance = 0, MaxMacMaxStat = 0, MaxDcChance = 0, MaxDcStatChance = 0, MaxDcMaxStat = 0, MaxMcChance = 0, MaxMcStatChance = 0, MaxMcMaxStat = 0, MaxScChance = 0, MaxScStatChance = 0, MaxScMaxStat = 0;
    unsigned char AccuracyChance = 0, AccuracyStatChance = 0, AccuracyMaxStat = 0, AgilityChance = 0, AgilityStatChance = 0, AgilityMaxStat = 0, HpChance = 0, HpStatChance = 0, HpMaxStat = 0, MpChance = 0, MpStatChance = 0, MpMaxStat = 0, StrongChance = 0, StrongStatChance = 0, StrongMaxStat = 0;
    unsigned char MagicResistChance = 0, MagicResistStatChance = 0, MagicResistMaxStat = 0, PoisonResistChance = 0, PoisonResistStatChance = 0, PoisonResistMaxStat = 0;
    unsigned char HpRecovChance = 0, HpRecovStatChance = 0, HpRecovMaxStat = 0, MpRecovChance = 0, MpRecovStatChance = 0, MpRecovMaxStat = 0, PoisonRecovChance = 0, PoisonRecovStatChance = 0, PoisonRecovMaxStat = 0;
    unsigned char CriticalRateChance = 0, CriticalRateStatChance = 0, CriticalRateMaxStat = 0, CriticalDamageChance = 0, CriticalDamageStatChance = 0, CriticalDamageMaxStat = 0;
    unsigned char FreezeChance = 0, FreezeStatChance = 0, FreezeMaxStat = 0, PoisonAttackChance = 0, PoisonAttackStatChance = 0, PoisonAttackMaxStat = 0;
    unsigned char AttackSpeedChance = 0, AttackSpeedStatChance = 0, AttackSpeedMaxStat = 0, LuckChance = 0, LuckStatChance = 0, LuckMaxStat = 0;
    unsigned char CurseChance = 0;
    unsigned char SlotChance = 0, SlotStatChance = 0, SlotMaxStat = 0;

    RandomItemStat(ItemType Type = ItemType::Book);

    void SetWeapon();
    void SetArmour();
    void SetHelmet();
    void SetBeltBoots();
    void SetNecklace();
    void SetBracelet();
    void SetRing();

    void SetMount();
};

class ChatItem
{
public:
    unsigned long long UniqueID = 0;
    std::string Title;
    MirGridType Grid = static_cast<MirGridType>(0);

    std::string getRegexInternalName() const;

    std::string getInternalName() const;

    ChatItem();

    ChatItem(BinaryReader *reader);

    void Save(BinaryWriter *writer);
};
